package meta

import (
	"github.com/ghodss/yaml"
	ui "github.com/gizak/termui/v3"
	"github.com/gizak/termui/v3/widgets"
)

func (p *Presenter) Show(backupInfoHandler BackupInfoHandler, timeRangeHandler TimeRangeHandler) error {
	if err := ui.Init(); err != nil {
		return err
	}
	defer ui.Close()

	backupInfoUi := p.NewList()
	timeRangeInfoUi := p.NewList()
	backupInfoDetailUi := p.NewParagraph()

	grid := ui.NewGrid()
	termWidth, termHeight := ui.TerminalDimensions()
	grid.SetRect(0, 0, termWidth, termHeight)
	grid.Title = p.Title
	grid.Set(
		ui.NewRow(1.0,
			ui.NewCol(1.0/2, ui.NewRow(1.0/2, backupInfoUi), ui.NewRow(1.0/2, timeRangeInfoUi)),
			ui.NewCol(1.0/2, backupInfoDetailUi),
		),
	)
	p.layout = grid
	go p.showController(backupInfoUi)
	go p.backupInfoDetailController(backupInfoDetailUi)

	for {
		select {
		case <-p.ctx.Done():
			return nil
		case p.currentMetaCr = <-p.metaChan:
			backupInfoUi.Rows = backupInfoHandler(p.currentMetaCr)
			backupInfoDetailUi.Text = p.parserBackupInfo()
			timeRangeInfoUi.Rows = timeRangeHandler(p.currentMetaCr)
			p.refreshUI()
		}
	}
}

func (p *Presenter) NewList() *widgets.List {
	l := widgets.NewList()
	l.TextStyle = ui.NewStyle(ui.ColorClear)
	l.WrapText = false
	l.SelectedRowStyle = ui.NewStyle(ui.ColorCyan)
	p.widgets = append(p.widgets, l)
	return l
}

func (p *Presenter) NewParagraph() *widgets.Paragraph {
	l := widgets.NewParagraph()
	l.TextStyle = ui.NewStyle(ui.ColorClear)
	l.WrapText = false
	p.widgets = append(p.widgets, l)
	return l
}

func (p *Presenter) backupInfoDetailController(l *widgets.Paragraph) {
	go func() {
		uiEvents := ui.PollEvents()
		for {
			_ = <-uiEvents
			l.Text = p.parserBackupInfo()
			p.refreshUI()
		}
	}()
}

func (p *Presenter) showController(l *widgets.List) {
	previousKey := ""
	go func() {
		uiEvents := ui.PollEvents()
		for {
			e := <-uiEvents
			switch e.ID {
			case "q", "Escape", "<C-c>":
				p.cancel()
				return
			case "j", "<Down>":
				l.ScrollDown()
			case "k", "<Up>":
				l.ScrollUp()
			case "<Chan-d>":
				l.ScrollHalfPageDown()
			case "<Chan-u>":
				l.ScrollHalfPageUp()
			case "<Chan-f>":
				l.ScrollPageDown()
			case "<Chan-b>":
				l.ScrollPageUp()
			case "g":
				if previousKey == "g" {
					l.ScrollTop()
				}
			case "<Home>":
				l.ScrollTop()
			case "G", "<End>":
				l.ScrollBottom()
			}

			if previousKey == "g" {
				previousKey = ""
			} else {
				previousKey = e.ID
			}
			p.selectIndex = l.SelectedRow
			p.refreshUI()
		}
	}()
}

func (p *Presenter) refreshUI() {
	ui.Render(p.layout)
}

func (p *Presenter) parserBackupInfo() string {
	backupInfos := p.currentMetaCr.Status.BackupInfos
	if backupInfos == nil || len(backupInfos) == 0 {
		return ""
	}
	if p.selectIndex > len(backupInfos) {
		p.selectIndex = len(backupInfos)
	}
	backupInfo := backupInfos[p.selectIndex]
	marshal, err := yaml.Marshal(backupInfo)
	if err != nil {
		return ""
	}
	return string(marshal)
}
